package openapi

import (
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io"
)

//用于表示返回结果的内置结构体
type DataResult struct {
	Name   string
	Values map[string]interface{}
}

func (s *DataResult) MarshalJSON() ([]byte, error) {
	return json.Marshal(s.Values)
}

func (s *DataResult) UnmarshalJSON(data []byte) error {
	return json.Unmarshal(data, &s.Values)
}

func (s *DataResult) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	s.Name = start.Name.Local

	token, err := d.Token()
	var parent = make(map[string]interface{})
	var grands = []map[string]interface{}{parent}
	var value string
	var prev int //0:start,1：end,2:char
	s.Values = parent
	for err == nil {
		if elem, ok := token.(xml.EndElement); ok {
			if prev == 2 {
				if len(grands) == 1 {
					break
				}
				grands[len(grands)-1][elem.Name.Local] = parent
				parent = grands[len(grands)-2]
			} else {
				parent[elem.Name.Local] = value
			}
			prev = 2
		} else if _, ok := token.(xml.StartElement); ok {
			if prev == 1 {
				grands = append(grands, parent)
				parent = make(map[string]interface{})
			}
			prev = 1
		} else if elem, ok := token.(xml.CharData); ok {
			prev = 3
			value = string(elem)
		}

		token, err = d.Token()
	}
	if err == nil || err == io.EOF {
		return nil
	}
	return err
}

// StringMap marshals into XML.
func (s *DataResult) MarshalXML(e *xml.Encoder, start xml.StartElement) error {

	if s.Name != "" {
		start.Name.Local = s.Name
	} else {
		start.Name.Local = "result"
	}
	tokens := []xml.Token{start}

	for key, value := range s.Values {
		t := xml.StartElement{Name: xml.Name{"", key}}
		var bts xml.CharData
		if value != nil {
			bts = xml.CharData(fmt.Sprintf("%v", value))
		} else {
			bts = xml.CharData("")
		}
		tokens = append(tokens, t, bts, xml.EndElement{t.Name})
	}

	tokens = append(tokens, xml.EndElement{start.Name})

	for _, t := range tokens {
		err := e.EncodeToken(t)
		if err != nil {
			return err
		}
	}

	// flush to ensure tokens are written
	return e.Flush()
}
